package com.yunfinal.api.tpl.template.directive.db;

import com.jfinal.core.JFinal;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.expr.ast.Id;
import com.jfinal.template.io.CharWriter;
import com.jfinal.template.io.FastStringWriter;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Scope;

/**
 * #sqlPara 指令方便定义SqlPara  https://www.jfinal.com/doc/5-13
 * <p>
 * 定义：
 * #xxxxx(xxxx)
 * 在此是SQL模版语法
 * #end
 * <p>
 * @author  杜福忠
 */
public abstract class SqlParaDirective extends Directive {
    protected Expr[] exprArray;
    protected String name;

    //SqlKit.SQL_PARA_KEY
    protected static final String SQL_PARA_KEY = "_SQL_PARA_";

    @Override
    public void setExprList(ExprList exprList) {
        exprArray = exprList.getExprArray();
        if (exprArray.length == 0) {
            return;
        }
        if ((exprArray[0] instanceof Id)) {
            this.name = ((Id) exprArray[0]).getId();
        }
    }

    @Override
    public void exec(Env env, Scope scope, Writer writer) {
        SqlPara sqlPara = new SqlPara();
        //放入数据域中
        scope.setLocal(SQL_PARA_KEY, sqlPara);

        //渲染SQL
        CharWriter charWriter = new CharWriter(64);
        FastStringWriter fsw = new FastStringWriter();
        charWriter.init(fsw);
        try {
            stat.exec(env, scope, charWriter);
        } finally {
            charWriter.close();
        }

        //移除sqlPara对象，避免污染Map
        scope.removeLocal(SQL_PARA_KEY);
        String sql = fsw.toString();
//        if (JFinal.me().getConstants().getDevMode()){
//            //待优化
//            sql = sql.replaceAll("\r\n|\r|\n", " ").replaceAll(" +", " ");
//        }
        sqlPara.setSql(sql);
        Object data = getData(DbConfigName.db(), sqlPara);
        scope.set(name, data);
    }

    @Override
    public boolean hasEnd() {
        return true;
    }

    protected abstract Object getData(DbPro db, SqlPara sqlPara);

    protected void setDefaultName(String name) {
        if (this.name == null) {
            this.name = name;
        }
    }

}









